/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: sw=2 ts=8 et : *//* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#include"LayerTransactionParent.h"#include<vector> // for vector#include"apz/src/AsyncPanZoomController.h"#include"CompositableHost.h" // for CompositableParent, Get, etc#include"ImageLayers.h" // for ImageLayer#include"Layers.h" // for Layer, ContainerLayer, etc#include"CompositableTransactionParent.h" // for EditReplyVector#include"CompositorBridgeParent.h"#include"gfxPrefs.h"#include"mozilla/gfx/BasePoint3D.h" // for BasePoint3D#include"mozilla/layers/AnimationHelper.h" // for GetAnimatedPropValue#include"mozilla/layers/CanvasLayerComposite.h"#include"mozilla/layers/ColorLayerComposite.h"#include"mozilla/layers/Compositor.h" // for Compositor#include"mozilla/layers/ContainerLayerComposite.h"#include"mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent#include"mozilla/layers/ImageLayerComposite.h"#include"mozilla/layers/LayerManagerComposite.h"#include"mozilla/layers/LayersMessages.h" // for EditReply, etc#include"mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG#include"mozilla/layers/TextureHostOGL.h" // for TextureHostOGL#include"mozilla/layers/PaintedLayerComposite.h"#include"mozilla/mozalloc.h" // for operator delete, etc#include"mozilla/SizePrintfMacros.h"#include"mozilla/Unused.h"#include"nsCoord.h" // for NSAppUnitsToFloatPixels#include"nsDebug.h" // for NS_RUNTIMEABORT#include"nsISupportsImpl.h" // for Layer::Release, etc#include"nsLayoutUtils.h" // for nsLayoutUtils#include"nsMathUtils.h" // for NS_round#include"nsPoint.h" // for nsPoint#include"nsTArray.h" // for nsTArray, nsTArray_Impl, etc#include"TreeTraversal.h" // for ForEachNode#include"GeckoProfiler.h"#include"mozilla/layers/TextureHost.h"#include"mozilla/layers/AsyncCompositionManager.h"usingmozilla::layout::RenderFrameParent;namespacemozilla{namespacelayers{//--------------------------------------------------// LayerTransactionParentLayerTransactionParent::LayerTransactionParent(HostLayerManager*aManager,CompositorBridgeParentBase*aBridge,uint64_taId):mLayerManager(aManager),mCompositorBridge(aBridge),mId(aId),mChildEpoch(0),mParentEpoch(0),mPendingTransaction(0),mDestroyed(false),mIPCOpen(false){}LayerTransactionParent::~LayerTransactionParent(){}voidLayerTransactionParent::SetLayerManager(HostLayerManager*aLayerManager){mLayerManager=aLayerManager;for(autoiter=mLayerMap.Iter();!iter.Done();iter.Next()){autolayer=iter.Data();layer->AsHostLayer()->SetLayerManager(aLayerManager);}}mozilla::ipc::IPCResultLayerTransactionParent::RecvShutdown(){Destroy();IProtocol*mgr=Manager();if(!Send__delete__(this)){returnIPC_FAIL_NO_REASON(mgr);}returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvShutdownSync(){returnRecvShutdown();}voidLayerTransactionParent::Destroy(){if(mDestroyed){return;}mDestroyed=true;mCompositables.clear();}classMOZ_STACK_CLASSAutoLayerTransactionParentAsyncMessageSender{public:explicitAutoLayerTransactionParentAsyncMessageSender(LayerTransactionParent*aLayerTransaction,constInfallibleTArray<OpDestroy>*aDestroyActors=nullptr):mLayerTransaction(aLayerTransaction),mActorsToDestroy(aDestroyActors){mLayerTransaction->SetAboutToSendAsyncMessages();}~AutoLayerTransactionParentAsyncMessageSender(){mLayerTransaction->SendPendingAsyncMessages();if(mActorsToDestroy){// Destroy the actors after sending the async messages because the latter may contain// references to some actors.for(constauto&op:*mActorsToDestroy){mLayerTransaction->DestroyActor(op);}}}private:LayerTransactionParent*mLayerTransaction;constInfallibleTArray<OpDestroy>*mActorsToDestroy;};mozilla::ipc::IPCResultLayerTransactionParent::RecvPaintTime(constuint64_t&aTransactionId,constTimeDuration&aPaintTime){mCompositorBridge->UpdatePaintTime(this,aPaintTime);returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvInitReadLocks(ReadLockArray&&aReadLocks){if(!AddReadLocks(Move(aReadLocks))){returnIPC_FAIL_NO_REASON(this);}returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvUpdate(constTransactionInfo&aInfo){AutoProfilerTracingtracing("Paint","LayerTransaction");AUTO_PROFILER_LABEL("LayerTransactionParent::RecvUpdate",GRAPHICS);TimeStampupdateStart=TimeStamp::Now();MOZ_LAYERS_LOG(("[ParentSide] received txn with %"PRIuSIZE" edits",aInfo.cset().Length()));UpdateFwdTransactionId(aInfo.fwdTransactionId());AutoClearReadLocksclearLocks(mReadLocks);if(mDestroyed||!layer_manager()||layer_manager()->IsDestroyed()){for(constauto&op:aInfo.toDestroy()){DestroyActor(op);}returnIPC_OK();}// This ensures that destroy operations are always processed. It is not safe// to early-return from RecvUpdate without doing so.AutoLayerTransactionParentAsyncMessageSenderautoAsyncMessageSender(this,&aInfo.toDestroy());{AutoResolveRefLayersresolve(mCompositorBridge->GetCompositionManager(this));layer_manager()->BeginTransaction();}// Not all edits require an update to the hit testing tree.mUpdateHitTestingTree=false;for(EditArray::index_typei=0;i<aInfo.cset().Length();++i){constEdit&edit=const_cast<Edit&>(aInfo.cset()[i]);switch(edit.type()){// Create* opscaseEdit::TOpCreatePaintedLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreatePaintedLayer"));RefPtr<PaintedLayer>layer=layer_manager()->CreatePaintedLayer();if(!BindLayer(layer,edit.get_OpCreatePaintedLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreatePaintedLayer");break;}caseEdit::TOpCreateContainerLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreateContainerLayer"));RefPtr<ContainerLayer>layer=layer_manager()->CreateContainerLayer();if(!BindLayer(layer,edit.get_OpCreateContainerLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreateContainerLayer");break;}caseEdit::TOpCreateImageLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreateImageLayer"));RefPtr<ImageLayer>layer=layer_manager()->CreateImageLayer();if(!BindLayer(layer,edit.get_OpCreateImageLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreateImageLayer");break;}caseEdit::TOpCreateColorLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreateColorLayer"));RefPtr<ColorLayer>layer=layer_manager()->CreateColorLayer();if(!BindLayer(layer,edit.get_OpCreateColorLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreateColorLayer");break;}caseEdit::TOpCreateTextLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreateTextLayer"));RefPtr<TextLayer>layer=layer_manager()->CreateTextLayer();if(!BindLayer(layer,edit.get_OpCreateTextLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreateTextLayer");break;}caseEdit::TOpCreateBorderLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreateBorderLayer"));RefPtr<BorderLayer>layer=layer_manager()->CreateBorderLayer();if(!BindLayer(layer,edit.get_OpCreateBorderLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreateBorderLayer");break;}caseEdit::TOpCreateCanvasLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreateCanvasLayer"));RefPtr<CanvasLayer>layer=layer_manager()->CreateCanvasLayer();if(!BindLayer(layer,edit.get_OpCreateCanvasLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreateCanvasLayer");break;}caseEdit::TOpCreateRefLayer:{MOZ_LAYERS_LOG(("[ParentSide] CreateRefLayer"));RefPtr<RefLayer>layer=layer_manager()->CreateRefLayer();if(!BindLayer(layer,edit.get_OpCreateRefLayer())){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"CreateRefLayer");break;}caseEdit::TOpSetDiagnosticTypes:{mLayerManager->SetDiagnosticTypes(edit.get_OpSetDiagnosticTypes().diagnostics());break;}caseEdit::TOpWindowOverlayChanged:{mLayerManager->SetWindowOverlayChanged();break;}// Tree opscaseEdit::TOpSetRoot:{MOZ_LAYERS_LOG(("[ParentSide] SetRoot"));Layer*newRoot=AsLayer(edit.get_OpSetRoot().root());if(!newRoot){returnIPC_FAIL_NO_REASON(this);}if(newRoot->GetParent()){// newRoot is not a root!returnIPC_FAIL_NO_REASON(this);}mRoot=newRoot;UpdateHitTestingTree(mRoot,"SetRoot");break;}caseEdit::TOpInsertAfter:{MOZ_LAYERS_LOG(("[ParentSide] InsertAfter"));constOpInsertAfter&oia=edit.get_OpInsertAfter();Layer*child=AsLayer(oia.childLayer());Layer*layer=AsLayer(oia.container());Layer*after=AsLayer(oia.after());if(!child||!layer||!after){returnIPC_FAIL_NO_REASON(this);}ContainerLayer*container=layer->AsContainerLayer();if(!container||!container->InsertAfter(child,after)){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"InsertAfter");break;}caseEdit::TOpPrependChild:{MOZ_LAYERS_LOG(("[ParentSide] PrependChild"));constOpPrependChild&oac=edit.get_OpPrependChild();Layer*child=AsLayer(oac.childLayer());Layer*layer=AsLayer(oac.container());if(!child||!layer){returnIPC_FAIL_NO_REASON(this);}ContainerLayer*container=layer->AsContainerLayer();if(!container||!container->InsertAfter(child,nullptr)){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"PrependChild");break;}caseEdit::TOpRemoveChild:{MOZ_LAYERS_LOG(("[ParentSide] RemoveChild"));constOpRemoveChild&orc=edit.get_OpRemoveChild();Layer*childLayer=AsLayer(orc.childLayer());Layer*layer=AsLayer(orc.container());if(!childLayer||!layer){returnIPC_FAIL_NO_REASON(this);}ContainerLayer*container=layer->AsContainerLayer();if(!container||!container->RemoveChild(childLayer)){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"RemoveChild");break;}caseEdit::TOpRepositionChild:{MOZ_LAYERS_LOG(("[ParentSide] RepositionChild"));constOpRepositionChild&orc=edit.get_OpRepositionChild();Layer*child=AsLayer(orc.childLayer());Layer*after=AsLayer(orc.after());Layer*layer=AsLayer(orc.container());if(!child||!layer||!after){returnIPC_FAIL_NO_REASON(this);}ContainerLayer*container=layer->AsContainerLayer();if(!container||!container->RepositionChild(child,after)){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"RepositionChild");break;}caseEdit::TOpRaiseToTopChild:{MOZ_LAYERS_LOG(("[ParentSide] RaiseToTopChild"));constOpRaiseToTopChild&rtc=edit.get_OpRaiseToTopChild();Layer*child=AsLayer(rtc.childLayer());if(!child){returnIPC_FAIL_NO_REASON(this);}Layer*layer=AsLayer(rtc.container());if(!layer){returnIPC_FAIL_NO_REASON(this);}ContainerLayer*container=layer->AsContainerLayer();if(!container||!container->RepositionChild(child,nullptr)){returnIPC_FAIL_NO_REASON(this);}UpdateHitTestingTree(layer,"RaiseToTopChild");break;}caseEdit::TCompositableOperation:{if(!ReceiveCompositableUpdate(edit.get_CompositableOperation())){returnIPC_FAIL_NO_REASON(this);}break;}caseEdit::TOpAttachCompositable:{constOpAttachCompositable&op=edit.get_OpAttachCompositable();RefPtr<CompositableHost>host=FindCompositable(op.compositable());if(!Attach(AsLayer(op.layer()),host,false)){returnIPC_FAIL_NO_REASON(this);}host->SetCompositorBridgeID(mLayerManager->GetCompositorBridgeID());break;}caseEdit::TOpAttachAsyncCompositable:{constOpAttachAsyncCompositable&op=edit.get_OpAttachAsyncCompositable();RefPtr<ImageBridgeParent>imageBridge=ImageBridgeParent::GetInstance(OtherPid());if(!imageBridge){returnIPC_FAIL_NO_REASON(this);}RefPtr<CompositableHost>host=imageBridge->FindCompositable(op.compositable());if(!host){// This normally should not happen, but can after a GPU process crash.// Media may not have had time to update the ImageContainer associated// with a video frame, and we may try to attach a stale CompositableHandle.// Rather than break the whole transaction, we just continue.gfxCriticalNote<<"CompositableHost "<<op.compositable().Value()<<" not found";continue;}if(!Attach(AsLayer(op.layer()),host,true)){returnIPC_FAIL_NO_REASON(this);}host->SetCompositorBridgeID(mLayerManager->GetCompositorBridgeID());break;}default:MOZ_CRASH("not reached");}}// Process simple attribute updates.for(constauto&op:aInfo.setSimpleAttrs()){MOZ_LAYERS_LOG(("[ParentSide] SetSimpleLayerAttributes"));Layer*layer=AsLayer(op.layer());if(!layer){returnIPC_FAIL_NO_REASON(this);}constSimpleLayerAttributes&attrs=op.attrs();constSimpleLayerAttributes&orig=layer->GetSimpleAttributes();if(!attrs.HitTestingInfoIsEqual(orig)){UpdateHitTestingTree(layer,"scrolling info changed");}layer->SetSimpleAttributes(op.attrs());}// Process attribute updates.for(constauto&op:aInfo.setAttrs()){MOZ_LAYERS_LOG(("[ParentSide] SetLayerAttributes"));if(!SetLayerAttributes(op)){returnIPC_FAIL_NO_REASON(this);}}// Process paints separately, after all normal edits.for(constauto&op:aInfo.paints()){if(!ReceiveCompositableUpdate(op)){returnIPC_FAIL_NO_REASON(this);}}mCompositorBridge->ShadowLayersUpdated(this,aInfo,mUpdateHitTestingTree);{AutoResolveRefLayersresolve(mCompositorBridge->GetCompositionManager(this));layer_manager()->EndTransaction(TimeStamp(),LayerManager::END_NO_IMMEDIATE_REDRAW);}if(!IsSameProcess()){// Ensure that any pending operations involving back and front// buffers have completed, so that neither process stomps on the// other's buffer contents.LayerManagerComposite::PlatformSyncBeforeReplyUpdate();}#ifdef COMPOSITOR_PERFORMANCE_WARNINGintcompositeTime=(int)(mozilla::TimeStamp::Now()-updateStart).ToMilliseconds();if(compositeTime>15){printf_stderr("Compositor: Layers update took %i ms (blocking gecko).\n",compositeTime);}#endif// Enable visual warning for long transaction when draw FPS option is enabledbooldrawFps=gfxPrefs::LayersDrawFPS();if(drawFps){uint32_tvisualWarningTrigger=gfxPrefs::LayerTransactionWarning();// The default theshold is 200ms to trigger, hit red when it take 4 times longerTimeDurationlatency=TimeStamp::Now()-aInfo.transactionStart();if(latency>TimeDuration::FromMilliseconds(visualWarningTrigger)){floatseverity=(latency-TimeDuration::FromMilliseconds(visualWarningTrigger)).ToMilliseconds()/(4*visualWarningTrigger);if(severity>1.f){severity=1.f;}mLayerManager->VisualFrameWarning(severity);printf_stderr("LayerTransactionParent::RecvUpdate transaction from process %d took %f ms",OtherPid(),latency.ToMilliseconds());}mLayerManager->RecordUpdateTime((TimeStamp::Now()-updateStart).ToMilliseconds());}returnIPC_OK();}boolLayerTransactionParent::SetLayerAttributes(constOpSetLayerAttributes&aOp){Layer*layer=AsLayer(aOp.layer());if(!layer){returnfalse;}constLayerAttributes&attrs=aOp.attrs();constCommonLayerAttributes&common=attrs.common();if(common.visibleRegion()!=layer->GetVisibleRegion()){UpdateHitTestingTree(layer,"visible region changed");layer->SetVisibleRegion(common.visibleRegion());}if(common.eventRegions()!=layer->GetEventRegions()){UpdateHitTestingTree(layer,"event regions changed");layer->SetEventRegions(common.eventRegions());}Maybe<ParentLayerIntRect>clipRect=common.useClipRect()?Some(common.clipRect()):Nothing();if(clipRect!=layer->GetClipRect()){UpdateHitTestingTree(layer,"clip rect changed");layer->SetClipRect(clipRect);}if(LayerHandlemaskLayer=common.maskLayer()){layer->SetMaskLayer(AsLayer(maskLayer));}else{layer->SetMaskLayer(nullptr);}layer->SetCompositorAnimations(common.compositorAnimations());// Clean up the Animations by id in the CompositorAnimationStorage// if there are no active animations on the layerif(layer->GetCompositorAnimationsId()&&layer->GetAnimations().IsEmpty()){CompositorAnimationStorage*storage=mCompositorBridge->GetAnimationStorage(GetId());if(storage){storage->ClearById(layer->GetCompositorAnimationsId());}}if(common.scrollMetadata()!=layer->GetAllScrollMetadata()){UpdateHitTestingTree(layer,"scroll metadata changed");layer->SetScrollMetadata(common.scrollMetadata());}layer->SetDisplayListLog(common.displayListLog().get());// The updated invalid region is added to the existing one, since we can// update multiple times before the next composite.layer->AddInvalidRegion(common.invalidRegion());nsTArray<RefPtr<Layer>>maskLayers;for(size_ti=0;i<common.ancestorMaskLayers().Length();i++){Layer*maskLayer=AsLayer(common.ancestorMaskLayers().ElementAt(i));if(!maskLayer){returnfalse;}maskLayers.AppendElement(maskLayer);}layer->SetAncestorMaskLayers(maskLayers);typedefSpecificLayerAttributesSpecific;constSpecificLayerAttributes&specific=attrs.specific();switch(specific.type()){caseSpecific::Tnull_t:break;caseSpecific::TPaintedLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] painted layer"));PaintedLayer*paintedLayer=layer->AsPaintedLayer();if(!paintedLayer){returnfalse;}constPaintedLayerAttributes&attrs=specific.get_PaintedLayerAttributes();paintedLayer->SetValidRegion(attrs.validRegion());break;}caseSpecific::TContainerLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] container layer"));ContainerLayer*containerLayer=layer->AsContainerLayer();if(!containerLayer){returnfalse;}constContainerLayerAttributes&attrs=specific.get_ContainerLayerAttributes();containerLayer->SetPreScale(attrs.preXScale(),attrs.preYScale());containerLayer->SetInheritedScale(attrs.inheritedXScale(),attrs.inheritedYScale());containerLayer->SetScaleToResolution(attrs.scaleToResolution(),attrs.presShellResolution());if(attrs.eventRegionsOverride()!=containerLayer->GetEventRegionsOverride()){UpdateHitTestingTree(layer,"event regions override changed");containerLayer->SetEventRegionsOverride(attrs.eventRegionsOverride());}break;}caseSpecific::TColorLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] color layer"));ColorLayer*colorLayer=layer->AsColorLayer();if(!colorLayer){returnfalse;}colorLayer->SetColor(specific.get_ColorLayerAttributes().color().value());colorLayer->SetBounds(specific.get_ColorLayerAttributes().bounds());break;}caseSpecific::TTextLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] text layer"));TextLayer*textLayer=layer->AsTextLayer();if(!textLayer){returnfalse;}constauto&tla=specific.get_TextLayerAttributes();textLayer->SetBounds(tla.bounds());textLayer->SetGlyphs(Move(const_cast<nsTArray<GlyphArray>&>(tla.glyphs())));textLayer->SetScaledFont(reinterpret_cast<gfx::ScaledFont*>(tla.scaledFont()));break;}caseSpecific::TBorderLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] border layer"));BorderLayer*borderLayer=layer->AsBorderLayer();if(!borderLayer){returnfalse;}borderLayer->SetRect(specific.get_BorderLayerAttributes().rect());borderLayer->SetColors(specific.get_BorderLayerAttributes().colors());borderLayer->SetCornerRadii(specific.get_BorderLayerAttributes().corners());borderLayer->SetWidths(specific.get_BorderLayerAttributes().widths());break;}caseSpecific::TCanvasLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] canvas layer"));CanvasLayer*canvasLayer=layer->AsCanvasLayer();if(!canvasLayer){returnfalse;}canvasLayer->SetSamplingFilter(specific.get_CanvasLayerAttributes().samplingFilter());canvasLayer->SetBounds(specific.get_CanvasLayerAttributes().bounds());break;}caseSpecific::TRefLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] ref layer"));RefLayer*refLayer=layer->AsRefLayer();if(!refLayer){returnfalse;}refLayer->SetReferentId(specific.get_RefLayerAttributes().id());refLayer->SetEventRegionsOverride(specific.get_RefLayerAttributes().eventRegionsOverride());UpdateHitTestingTree(layer,"event regions override changed");break;}caseSpecific::TImageLayerAttributes:{MOZ_LAYERS_LOG(("[ParentSide] image layer"));ImageLayer*imageLayer=layer->AsImageLayer();if(!imageLayer){returnfalse;}constImageLayerAttributes&attrs=specific.get_ImageLayerAttributes();imageLayer->SetSamplingFilter(attrs.samplingFilter());imageLayer->SetScaleToSize(attrs.scaleToSize(),attrs.scaleMode());break;}default:MOZ_CRASH("not reached");}returntrue;}mozilla::ipc::IPCResultLayerTransactionParent::RecvSetLayerObserverEpoch(constuint64_t&aLayerObserverEpoch){mChildEpoch=aLayerObserverEpoch;returnIPC_OK();}boolLayerTransactionParent::ShouldParentObserveEpoch(){if(mParentEpoch==mChildEpoch){returnfalse;}mParentEpoch=mChildEpoch;returntrue;}mozilla::ipc::IPCResultLayerTransactionParent::RecvSetTestSampleTime(constTimeStamp&aTime){if(!mCompositorBridge->SetTestSampleTime(GetId(),aTime)){returnIPC_FAIL_NO_REASON(this);}returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvLeaveTestMode(){mCompositorBridge->LeaveTestMode(GetId());returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvGetAnimationOpacity(constuint64_t&aCompositorAnimationsId,float*aOpacity,bool*aHasAnimationOpacity){*aHasAnimationOpacity=false;if(mDestroyed||!layer_manager()||layer_manager()->IsDestroyed()){returnIPC_FAIL_NO_REASON(this);}mCompositorBridge->ApplyAsyncProperties(this);CompositorAnimationStorage*storage=mCompositorBridge->GetAnimationStorage(GetId());if(!storage){returnIPC_FAIL_NO_REASON(this);}Maybe<float>opacity=storage->GetAnimationOpacity(aCompositorAnimationsId);if(opacity){*aOpacity=*opacity;*aHasAnimationOpacity=true;}returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvGetAnimationTransform(constuint64_t&aCompositorAnimationsId,MaybeTransform*aTransform){if(mDestroyed||!layer_manager()||layer_manager()->IsDestroyed()){returnIPC_FAIL_NO_REASON(this);}// Make sure we apply the latest animation style or else we can end up with// a race between when we temporarily clear the animation transform (in// CompositorBridgeParent::SetShadowProperties) and when animation recalculates// the value.mCompositorBridge->ApplyAsyncProperties(this);CompositorAnimationStorage*storage=mCompositorBridge->GetAnimationStorage(GetId());if(!storage){returnIPC_FAIL_NO_REASON(this);}Maybe<Matrix4x4>transform=storage->GetAnimationTransform(aCompositorAnimationsId);if(transform){*aTransform=*transform;}else{*aTransform=mozilla::void_t();}returnIPC_OK();}staticAsyncPanZoomController*GetAPZCForViewID(Layer*aLayer,FrameMetrics::ViewIDaScrollID){AsyncPanZoomController*resultApzc=nullptr;ForEachNode<ForwardIterator>(aLayer,[aScrollID,&resultApzc](Layer*layer){for(uint32_ti=0;i<layer->GetScrollMetadataCount();i++){if(layer->GetFrameMetrics(i).GetScrollId()==aScrollID){resultApzc=layer->GetAsyncPanZoomController(i);returnTraversalFlag::Abort;}}returnTraversalFlag::Continue;});returnresultApzc;}mozilla::ipc::IPCResultLayerTransactionParent::RecvSetAsyncScrollOffset(constFrameMetrics::ViewID&aScrollID,constfloat&aX,constfloat&aY){if(mDestroyed||!layer_manager()||layer_manager()->IsDestroyed()){returnIPC_FAIL_NO_REASON(this);}AsyncPanZoomController*controller=GetAPZCForViewID(mRoot,aScrollID);if(!controller){returnIPC_FAIL_NO_REASON(this);}controller->SetTestAsyncScrollOffset(CSSPoint(aX,aY));returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvSetAsyncZoom(constFrameMetrics::ViewID&aScrollID,constfloat&aValue){if(mDestroyed||!layer_manager()||layer_manager()->IsDestroyed()){returnIPC_FAIL_NO_REASON(this);}AsyncPanZoomController*controller=GetAPZCForViewID(mRoot,aScrollID);if(!controller){returnIPC_FAIL_NO_REASON(this);}controller->SetTestAsyncZoom(LayerToParentLayerScale(aValue));returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvFlushApzRepaints(){mCompositorBridge->FlushApzRepaints(GetId());returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvGetAPZTestData(APZTestData*aOutData){mCompositorBridge->GetAPZTestData(GetId(),aOutData);returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvRequestProperty(constnsString&aProperty,float*aValue){*aValue=-1;returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvSetConfirmedTargetAPZC(constuint64_t&aBlockId,nsTArray<ScrollableLayerGuid>&&aTargets){mCompositorBridge->SetConfirmedTargetAPZC(GetId(),aBlockId,aTargets);returnIPC_OK();}boolLayerTransactionParent::Attach(Layer*aLayer,CompositableHost*aCompositable,boolaIsAsync){if(!aCompositable||!aLayer){returnfalse;}HostLayer*layer=aLayer->AsHostLayer();if(!layer){returnfalse;}TextureSourceProvider*provider=static_cast<HostLayerManager*>(aLayer->Manager())->GetTextureSourceProvider();if(!layer->SetCompositableHost(aCompositable)){// not all layer types accept a compositable, see bug 967824returnfalse;}aCompositable->Attach(aLayer,provider,aIsAsync?CompositableHost::ALLOW_REATTACH|CompositableHost::KEEP_ATTACHED:CompositableHost::NO_FLAGS);returntrue;}mozilla::ipc::IPCResultLayerTransactionParent::RecvClearCachedResources(){if(mRoot){// NB: |mRoot| here is the *child* context's root. In this parent// context, it's just a subtree root. We need to scope the clear// of resources to exactly that subtree, so we specify it here.mLayerManager->ClearCachedResources(mRoot);}mCompositorBridge->NotifyClearCachedResources(this);returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvForceComposite(){mCompositorBridge->ForceComposite(this);returnIPC_OK();}voidLayerTransactionParent::ActorDestroy(ActorDestroyReasonwhy){Destroy();}boolLayerTransactionParent::AllocShmem(size_taSize,ipc::SharedMemory::SharedMemoryTypeaType,ipc::Shmem*aShmem){if(!mIPCOpen||mDestroyed){returnfalse;}returnPLayerTransactionParent::AllocShmem(aSize,aType,aShmem);}boolLayerTransactionParent::AllocUnsafeShmem(size_taSize,ipc::SharedMemory::SharedMemoryTypeaType,ipc::Shmem*aShmem){if(!mIPCOpen||mDestroyed){returnfalse;}returnPLayerTransactionParent::AllocUnsafeShmem(aSize,aType,aShmem);}voidLayerTransactionParent::DeallocShmem(ipc::Shmem&aShmem){if(!mIPCOpen||mDestroyed){return;}PLayerTransactionParent::DeallocShmem(aShmem);}boolLayerTransactionParent::IsSameProcess()const{returnOtherPid()==base::GetCurrentProcId();}voidLayerTransactionParent::SendAsyncMessage(constInfallibleTArray<AsyncParentMessageData>&aMessage){MOZ_ASSERT_UNREACHABLE("unexpected to be called");}voidLayerTransactionParent::SendPendingAsyncMessages(){mCompositorBridge->SendPendingAsyncMessages();}voidLayerTransactionParent::SetAboutToSendAsyncMessages(){mCompositorBridge->SetAboutToSendAsyncMessages();}voidLayerTransactionParent::NotifyNotUsed(PTextureParent*aTexture,uint64_taTransactionId){MOZ_ASSERT_UNREACHABLE("unexpected to be called");}boolLayerTransactionParent::BindLayerToHandle(RefPtr<Layer>aLayer,constLayerHandle&aHandle){if(!aHandle||!aLayer){returnfalse;}if(autoentry=mLayerMap.LookupForAdd(aHandle.Value())){returnfalse;}else{entry.OrInsert([&aLayer](){returnaLayer;});}returntrue;}Layer*LayerTransactionParent::AsLayer(constLayerHandle&aHandle){if(!aHandle){returnnullptr;}returnmLayerMap.GetWeak(aHandle.Value());}mozilla::ipc::IPCResultLayerTransactionParent::RecvNewCompositable(constCompositableHandle&aHandle,constTextureInfo&aInfo){if(!AddCompositable(aHandle,aInfo)){returnIPC_FAIL_NO_REASON(this);}returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvReleaseLayer(constLayerHandle&aHandle){RefPtr<Layer>layer;if(!aHandle||!mLayerMap.Remove(aHandle.Value(),getter_AddRefs(layer))){returnIPC_FAIL_NO_REASON(this);}layer->Disconnect();returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvReleaseCompositable(constCompositableHandle&aHandle){ReleaseCompositable(aHandle);returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvRecordPaintTimes(constPaintTiming&aTiming){// Currently we only add paint timings for remote layers. In the future// we could be smarter and use paint timings from the UI process, either// as a separate overlay or if no remote layers are attached.if(mLayerManager&&mCompositorBridge->IsRemote()){mLayerManager->RecordPaintTimes(aTiming);}returnIPC_OK();}mozilla::ipc::IPCResultLayerTransactionParent::RecvGetTextureFactoryIdentifier(TextureFactoryIdentifier*aIdentifier){if(!mLayerManager){// Default constructor sets mParentBackend to LAYERS_NONE.returnIPC_OK();}*aIdentifier=mLayerManager->GetTextureFactoryIdentifier();returnIPC_OK();}}// namespace layers}// namespace mozilla